package com.linkgie.galaxyframework.utils.bean;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Bean 对象元数据；
 */
public class BeanMetadata {

    private static final Object MUTEX = new Object();

    private static final Map<Class<?>, BeanMetadata> beanMetadatas = new ConcurrentHashMap<>();

    public static BeanMetadata resolve(Class<?> entityType){
        BeanMetadata metadata = beanMetadatas.get(entityType);
        if (metadata == null) {
            synchronized(MUTEX){
                metadata = beanMetadatas.get(entityType);
                if (metadata == null) {
                    metadata = new BeanMetadata(entityType);
                    beanMetadatas.put(entityType, metadata);
                }
            }
        }
        return metadata;
    }


    //--------------------------------------------

    private Class<?> beanType;

    /**
     * 属性清单及其对应的类型；
     * <p>
     * 注：关于线程安全，由于是在构造函数中进行初始化，因此采用 HashMap 是线程安全的；
     */
    private Map<String, Class<?>> fieldTypes = new HashMap<>();

    /**
     * 属性的 Get 方法与属性名称的映射；
     * <p>
     * 注：关于线程安全，由于是在构造函数中进行初始化，因此采用 HashMap 是线程安全的；
     */
    private Map<Method, String> fieldGetterMethods = new HashMap<>();

    //TODO: 缓存类型的元数据，优化性能；
    private BeanMetadata(Class<?> entityType) {
        this.beanType = entityType;

        resolve();
    }

    private void resolve() {
        Method[] methods = beanType.getMethods();

        for (Method method : methods) {
            // 检查是否是 POJO 的 getter 方法；
            if (method.getParameterCount() != 0
                    || method.getReturnType() == void.class
                    || method.getName().equals("getClass")
                    || (!method.getName().startsWith("get")
                            && !(method.getName().startsWith("is")&& method.getReturnType() == boolean.class))) {
                continue;
            }

            String fieldName;
            if (method.getName().startsWith("get")) {
                // getXXX();
                fieldName = method.getName().substring(3);
                fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
            }else{
                // isXXX();
                fieldName = method.getName().substring(2);
                fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
            }

            Class<?> fieldType = method.getReturnType();

            fieldTypes.put(fieldName, fieldType);
            fieldGetterMethods.put(method, fieldName);
        }
    }

    /**
     * @return the entityType
     */
    public Class<?> getBeanType() {
        return beanType;
    }

    /**
     * 返回指定方法对应的属性名称；
     * <p>
     * 注：如果指定的方法不是 POJO 的 getter 方法，则返回 null；
     * 
     * @param method
     * @return
     */
    public String getFieldName(Method method) {
        return fieldGetterMethods.get(method);
    }

    /**
     * 返回指定属性名称对应的属性类型；
     * 
     * @param fieldName
     * @return
     */
    public Class<?> getFieldType(String fieldName) {
        return fieldTypes.get(fieldName);
    }

    /**
     * 所有的属性名称；
     * @return
     */
    public Collection<String> getFieldNames(){
        return fieldTypes.keySet();
    }
}
